import { Vector2D } from '../utils/Vector2D';
import { SnakeEffectManager, ConsumptionEffectType } from '../systems/SnakeEffectManager';

type SnakeState = {
    boost: boolean;
    shield: boolean;
    poisoned: boolean;
    invincible: boolean;
    magnetized: boolean;
};

export class Snake {
    private segments: Vector2D[] = [];
    private direction: Vector2D;
    private velocity: Vector2D;
    private readonly baseSpeed: number = 0.3;
    private currentSpeed: number = this.baseSpeed;
    private energy: number = 100;
    private readonly maxEnergy: number = 100;
    private state: SnakeState;
    private stateTimers: Map<string, number>;
    private effectManager: SnakeEffectManager;

    constructor(startPosition: Vector2D) {
        // 初始化蛇的身体段
        this.segments.push(startPosition);
        for (let i = 1; i < 5; i++) {
            this.segments.push(new Vector2D(
                startPosition.x - i * 20,
                startPosition.y
            ));
        }

        this.direction = new Vector2D(1, 0);
        this.velocity = this.direction.multiply(this.baseSpeed);
        this.state = {
            boost: false,
            shield: false,
            poisoned: false,
            invincible: false,
            magnetized: false
        };
        this.stateTimers = new Map();
        this.effectManager = new SnakeEffectManager();
    }

    public update(deltaTime: number, input: { direction: Vector2D; boost: boolean; shield: boolean }): void {
        // 更新方向
        if (!input.direction.equals(new Vector2D(0, 0))) {
            // 计算转向角度，实现平滑转向
            const targetAngle = input.direction.angle();
            const currentAngle = this.direction.angle();
            let angleDiff = targetAngle - currentAngle;

            // 处理角度差跨越360度的情况
            if (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
            if (angleDiff < -Math.PI) angleDiff += Math.PI * 2;

            const turnSpeed = 0.15; // 增加转向速度

            // 使用插值实现平滑转向
            const newAngle = currentAngle + angleDiff * turnSpeed;
            this.direction = new Vector2D(Math.cos(newAngle), Math.sin(newAngle)).normalize();
        }

        // 更新状态
        this.updateState(input);

        // 更新速度
        this.updateVelocity();

        // 更新位置
        this.updatePosition(deltaTime);

        // 更新状态计时器
        this.updateStateTimers(deltaTime);

        // 更新视觉效果
        this.effectManager.updateEffects(this.segments, deltaTime);
    }

    private updatePosition(deltaTime: number): void {
        // 更新头部位置
        const newHead = this.segments[0].add(this.velocity.multiply(deltaTime));
        this.segments[0] = newHead;

        // 更新身体段位置，确保每段之间保持固定距离
        const segmentSpacing = 20;
        for (let i = 1; i < this.segments.length; i++) {
            const target = this.segments[i - 1];
            const current = this.segments[i];
            const direction = target.subtract(current).normalize();
            const idealPosition = target.subtract(direction.multiply(segmentSpacing));
            this.segments[i] = idealPosition;
        }
    }

    private updateState(input: { direction: Vector2D; boost: boolean; shield: boolean }): void {
        // 处理加速
        if (input.boost && this.energy > 0) {
            this.state.boost = true;
            this.energy = Math.max(0, this.energy - 0.5);
        } else {
            this.state.boost = false;
            this.energy = Math.min(this.maxEnergy, this.energy + 0.1);
        }

        // 处理护盾
        this.state.shield = input.shield && this.energy > 30;
        if (this.state.shield) {
            this.energy = Math.max(0, this.energy - 0.3);
        }
    }

    private updateVelocity(): void {
        let speedMultiplier = 1;

        // 加速效果
        if (this.state.boost) speedMultiplier *= 1.8; // 增强加速效果

        // 中毒减速效果
        if (this.state.poisoned) speedMultiplier *= 0.6; // 加重减速效果

        // 根据长度动态调整速度
        let lengthFactor;
        if (this.segments.length <= 10) {
            lengthFactor = 1;
        } else if (this.segments.length <= 30) {
            lengthFactor = 0.9 + (30 - this.segments.length) * 0.005;
        } else {
            lengthFactor = Math.max(0.7, 0.9 - (this.segments.length - 30) * 0.002);
        }
        speedMultiplier *= lengthFactor;

        // 护盾状态下微量减速
        if (this.state.shield) speedMultiplier *= 0.9;

        this.currentSpeed = this.baseSpeed * speedMultiplier;
        this.velocity = this.direction.multiply(this.currentSpeed);
    }

    private updateStateTimers(deltaTime: number): void {
        for (const [state, time] of this.stateTimers.entries()) {
            const newTime = time - deltaTime;
            if (newTime <= 0) {
                this.stateTimers.delete(state);
                this.state[state as keyof SnakeState] = false;
            } else {
                this.stateTimers.set(state, newTime);
            }
        }
    }

    public grow(lengthMultiplier: number = 1): void {
        const lastSegment = this.segments[this.segments.length - 1];
        const secondLastSegment = this.segments[this.segments.length - 2];
        const direction = lastSegment.subtract(secondLastSegment).normalize();
        
        // 根据长度倍增器添加多个段
        const segmentsToAdd = Math.max(1, Math.floor(lengthMultiplier));
        for (let i = 0; i < segmentsToAdd; i++) {
            const newSegment = lastSegment.add(direction.multiply(20));
            this.segments.push(newSegment);
        }
    }

    /**
     * 处理食物吞噬效果
     */
    public consumeFood(foodType: string, position: Vector2D): void {
        let effectType: ConsumptionEffectType = 'normal';
        
        // 根据食物类型确定效果类型
        switch (foodType) {
            case 'poison':
                effectType = 'poison';
                break;
            case 'magnet':
                effectType = 'magnet';
                break;
            default:
                effectType = 'normal';
                break;
        }
        
        // 添加吞噬效果
        this.effectManager.addConsumptionEffect(position, effectType);
    }

    public applyEffect(effect: keyof SnakeState, duration: number): void {
        this.state[effect] = true;
        this.stateTimers.set(effect, duration);
    }

    public getSegments(): Vector2D[] {
        return this.segments;
    }

    public getHead(): Vector2D {
        return this.segments[0];
    }

    public getDirection(): Vector2D {
        return this.direction;
    }

    public getState(): SnakeState {
        return { ...this.state };
    }

    public getEnergy(): number {
        return this.energy;
    }

    public getEffectManager(): SnakeEffectManager {
        return this.effectManager;
    }
}